import { FC, useCallback, useState } from "react"
import { ActivityIndicator, TextStyle, View, ViewStyle } from "react-native"
import * as ImagePicker from "expo-image-picker"

import { Button } from "@/components/Button"
import { TextField } from "@/components/TextField"
import { AgentModel } from "@/services/api/agents"
import { useAppTheme } from "@/theme/context"
import type { ThemedStyle } from "@/theme/types"
import { uploadFiles } from "@/utils/uploadFiles"
import { useSafeAreaInsetsStyle } from "@/utils/useSafeAreaInsetsStyle"

export interface AgentInputProps {
  /**
   * 触发发送消息，返回Promise可方便在父组件中处理状态
   */
  onSend: (input: string, attachments: string[]) => Promise<void> | void
  /**
   * 外部传入的加载状态
   */
  isLoading?: boolean
  /**
   * 图片更新时回调
   */
  onImagesChange?: (images: string[]) => void
  /**
   * 输入框占位符
   */
  placeholder?: string
  /**
   * 当前模型
   */
  agent?: AgentModel
}

export const AgentInput: FC<AgentInputProps> = ({
  onSend,
  isLoading = false,
  onImagesChange,
  placeholder = "输入消息...",
  agent,
}) => {
  const { themed } = useAppTheme()
  const $inputContainerInsets = useSafeAreaInsetsStyle(["bottom"])

  const [text, setText] = useState("")
  const [isUploading, setIsUploading] = useState(false)

  const handleUpload = useCallback(async () => {
    if (isLoading || isUploading) return
    const result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ["images"],
      allowsMultipleSelection: true,
      selectionLimit: 5,
    })

    if (result.canceled || !result.assets.length) return

    try {
      setIsUploading(true)
      const uploaded = (await uploadFiles({
        folder: "user_images",
        filePaths: result.assets.map((asset) => asset.uri),
        region: "ap-shanghai",
      })) as unknown as string[] | undefined

      if (!uploaded?.length) return
      onImagesChange?.(uploaded)
    } catch (error) {
      console.warn("Upload failed:", error)
    } finally {
      setIsUploading(false)
    }
  }, [isLoading, isUploading, onImagesChange])

  const handleSend = useCallback(async () => {
    const value = text.trim()
    if (!value || isLoading) return

    try {
      await onSend(value, [])
      setText("")
    } catch (error) {
      console.warn("Send message error:", error)
    }
  }, [isLoading, onSend, text])

  const showSpinner = isLoading || isUploading

  return (
    <View style={themed([$inputContainer, $inputContainerInsets])}>
      <View style={themed($inputWrapper)}>
        {!!agent?.requestModalities.includes("text") && (
          <TextField
            placeholder={placeholder}
            value={text}
            multiline
            onChangeText={setText}
            style={themed($inputField)}
            containerStyle={themed($inputFieldContainer)}
          />
        )}
        {!!agent?.requestModalities.includes("text") && (
          <Button
            text={"发送"}
            onPress={handleSend}
            disabled={showSpinner || !text.trim()}
            style={themed($sendButton)}
            RightAccessory={
              showSpinner ? () => <ActivityIndicator size="small" color="white" /> : undefined
            }
          />
        )}
        {!!agent?.requestModalities.includes("image") && (
          <Button
            text={"上传图片"}
            onPress={handleUpload}
            disabled={showSpinner}
            style={themed($sendButton)}
            RightAccessory={
              showSpinner ? () => <ActivityIndicator size="small" color="white" /> : undefined
            }
          />
        )}
      </View>
    </View>
  )
}

const $inputContainer: ThemedStyle<ViewStyle> = ({ colors, spacing }) => ({
  backgroundColor: colors.palette.neutral100,
  paddingHorizontal: spacing.md,
  paddingVertical: spacing.sm,
  borderTopWidth: 1,
  borderTopColor: colors.palette.neutral300,
})

const $inputWrapper: ThemedStyle<ViewStyle> = ({ spacing }) => ({
  flexDirection: "row",
  alignItems: "flex-end",
  gap: spacing.sm,
})

const $inputFieldContainer: ThemedStyle<ViewStyle> = ({ colors }) => ({
  flex: 1,
  backgroundColor: colors.palette.neutral200,
  borderRadius: 20,
  borderWidth: 0,
})

const $inputField: ThemedStyle<TextStyle> = ({ colors }) => ({
  color: colors.text,
  maxHeight: 100,
})

const $sendButton: ThemedStyle<ViewStyle> = () => ({
  flex: 1,
  borderRadius: 20,
  paddingHorizontal: 20,
  minHeight: 40,
})

export default AgentInput
